#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <memory>
#include <stdexcept>


#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>


#include "User.h"
#include "Product.h"
#include "socket_utils.h" 


UserController g_userCtrl;
ProductController g_productCtrl;
// 互斥锁，用于保护对控制器的并发访问
std::mutex g_mutex;

// --- 客户端处理函数 ---

/**
 * 客户端请求：
 {
  "action": "ACTION_NAME",
  "payload": {
    "key1": "value1",
    "key2": 123
  }
}
 * 响应格式：
 {
  "status": "SUCCESS" | "ERROR",
  "message": "",
    "data": {
        "key1": "value1",
        "key2": 123
    }
}
 */
void handle_client(int client_socket)
{
    std::cout << "New client connected. Socket FD: " << client_socket << std::endl;

    int loggedInUserId = -1; // -1 表示未登录

    while (true)
    {
        std::string request_str;
        // 接收来自客户端的消息
        if (!receiveMessage(client_socket, request_str))
        {
            std::cout << "客户端连接中断 Socket FD: " << client_socket << std::endl;
            if (loggedInUserId != -1)
            {
                // 在C/S架构中，状态通常由客户端请求来改变，
                // 意外断开连接时，可能需要超时机制来清理会话，这里简化处理。
            }
            close(client_socket);
            return;
        }

        std::cout << "从客户端收到" << client_socket << ": " << request_str << std::endl;

        json request_json;
        json response_json;

        try
        {
            request_json = json::parse(request_str);
            std::string action = request_json.value("action", "");

            // --- 请求分发 ---
            // 在访问共享资源（控制器）之前加锁
            std::lock_guard<std::mutex> guard(g_mutex);

            if (action == "LOGIN")
            {
                std::string username = request_json["payload"]["username"];
                std::string password = request_json["payload"]["password"];
                response_json = g_userCtrl.handleLogin(username, password);
                if (response_json["status"] == "SUCCESS")
                {
                    loggedInUserId = response_json["data"]["id"].get<int>();
                }
            }
            else if (action == "REGISTER")
            {
                std::string username = request_json["payload"]["username"];
                std::string password = request_json["payload"]["password"];
                std::string userType = request_json["payload"]["userType"];
                response_json = g_userCtrl.handleRegister(username, password, userType);
                
            }
            else if (action == "CHANGE_USERNAME")
            {
                int uid = request_json["payload"]["userId"];
                std::string newName = request_json["payload"]["newUsername"];
                response_json = g_userCtrl.setUsername(uid, newName);
            }
            else if (action == "CHANGE_PASSWORD")
            {
                int uid = request_json["payload"]["userId"];
                std::string newPassword = request_json["payload"]["newPassword"];
                response_json = g_userCtrl.changePassword(uid, newPassword);
            }
            else if (action == "RECHARGE")
            {
                if (loggedInUserId == -1)
                {
                    response_json = {{"status", "ERROR"}, {"message", "User not logged in."}};
                }
                else
                {
                    double amount = request_json["payload"]["amount"];
                    // 你需要在 UserController 中实现 handleRecharge
                    response_json = g_userCtrl.handleRecharge(loggedInUserId, amount);
                }
            }
            else if (action == "CHECK_USERNAME")
            {
                std::string username = request_json["payload"]["username"];
                response_json["status"] = "SUCCESS";
                response_json["data"] = {{"exists", g_userCtrl.isUserNameExist(username)}};
            }
            else if (action == "GET_USER_INFO")
            {
                if (loggedInUserId == -1)
                {
                    response_json["status"] = "ERROR";
                    response_json["message"] = "用户未登录.";
                }
                else
                {
                    response_json = g_userCtrl.getUserDataById(loggedInUserId);
                    response_json["status"] = "SUCCESS";
                }
            }
            else if (action == "GET_ALL_PRODUCTS")
            {
                json product_array = json::array();
                const auto &products = g_productCtrl.getAllProducts();
                for (const auto &p : products)
                {
                    product_array.push_back(p->toJson());
                }
                response_json["status"] = "SUCCESS";
                response_json["data"] = product_array;
            }
            else if (action == "GET_MY_PRODUCTS")
            {
                if (loggedInUserId == -1)
                {
                    response_json["status"] = "ERROR";
                    response_json["message"] = "用户未登录.";
                }
                else
                {
                    response_json = g_productCtrl.handleGetMyProducts(loggedInUserId);
                }
            }
            else if (action == "GET_CART")
            {
                if (loggedInUserId == -1)
                {
                    response_json = {{"status", "ERROR"}, {"message", "User not logged in."}};
                }
                else
                {
                    response_json = g_userCtrl.handleGetCart(loggedInUserId, g_productCtrl);
                }
            }
            else if (action == "ADD_TO_CART")
            {
                if (loggedInUserId == -1)
                {
                    response_json["status"] = "ERROR";
                    response_json["message"] = "用户未登录.";
                }
                else
                {
                    std::string productId = request_json["payload"]["productId"];
                    int quantity = request_json["payload"]["quantity"];
                    response_json = g_userCtrl.handleAddToCart(loggedInUserId, productId, quantity, g_productCtrl);
                }
            }            
            else if (action == "UPDATE_CART_ITEM")
            {
                if (loggedInUserId == -1)
                {
                    response_json = {{"status", "ERROR"}, {"message", "User not logged in."}};
                }
                else
                {
                    std::string pid = request_json["payload"]["productId"];
                    int nq = request_json["payload"]["newQuantity"];
                    // 你需要在 UserController 中实现 handleUpdateCartItem
                    response_json = g_userCtrl.handleUpdateCartItem(loggedInUserId, pid, nq, g_productCtrl);
                }
            }
            else if (action == "CLEAR_CART")
            {
                if (loggedInUserId == -1)
                {
                    response_json = {{"status", "ERROR"}, {"message", "User not logged in."}};
                }
                else
                {
                    response_json = g_userCtrl.handleClearCart(loggedInUserId);
                }
            }
            else if (action == "CANCEL_ORDER")
            {
                if (loggedInUserId == -1)
                {
                    response_json = {{"status", "ERROR"}, {"message", "User not logged in."}};
                }
                else
                {
                    std::string oid = request_json["payload"]["orderId"];
                    response_json = g_userCtrl.handleCancelOrder(loggedInUserId, oid, g_productCtrl);
                }
            }
            else if (action == "CREATE_ORDER")
            {
                response_json = g_userCtrl.handleCreateOrder(loggedInUserId, g_productCtrl);
            }
            else if (action == "GET_UNPAID_ORDERS")
            {
                response_json = g_userCtrl.handleGetUnpaidOrders(loggedInUserId);
            }
            else if (action == "PAY_ORDER")
            {
                response_json = g_userCtrl.handlePayOrder(loggedInUserId, request_json["payload"]["orderId"], g_productCtrl);
            }
            else if (action == "CANCEL_ORDER")
            {
                response_json = g_userCtrl.handleCancelOrder(loggedInUserId, request_json["payload"]["orderId"], g_productCtrl);
            }

            else
            {
                response_json["status"] = "ERROR";
                response_json["message"] = "未知的操作.";
            }
        }
        catch (const json::parse_error &e)
        {
            response_json["status"] = "ERROR";
            response_json["message"] = "无效的 JSON 请求.";
            response_json["details"] = e.what();
        }

        // 发送响应回客户端
        sendMessage(client_socket, response_json.dump());
    }
}

// --- 服务器主函数 ---
int main()
{
    int server_fd;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    const int PORT = 8888;

    // 创建 socket 文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
    {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 将socket绑定到IP和端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 10) < 0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    std::cout << "服务器启动成功，正在端口 " << PORT << " 上监听..." << std::endl;

    
    while (true)
    {
        int new_socket;
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
        {
            perror("accept");
            continue; 
        }

        // 为每个客户端创建一个新线程进行处理
        std::thread client_thread(handle_client, new_socket);
        client_thread.detach(); // 让线程在后台独立运行
    }

    return 0;
}